package only.level5.railgun.ysartifactsimulation.utils;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import only.level5.railgun.ysartifactsimulation.Bean.CalcData;
import only.level5.railgun.ysartifactsimulation.Bean.CharacterScene;

import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

public class CalcUtils {

    public static void calcTotalDmg(CharacterScene scene) {
        double skillDmg = scene.getSkillDmg();
        double atk = scene.getAtk_ex() + scene.getAtk();
        Integer mastery = scene.getMastery();
        double increase = scene.getIncrease();
        Double reactionIncrease = scene.getReactionIncrease();
        double critRate = Math.min(scene.getCritRate(), 1);
        double critDmg = scene.getCritDmg();
        Double reaction = scene.getReaction();
        double reactionMagnification = 1;
        if (reaction > 1.0) {
            reactionMagnification = reaction * (1 + 2.78 * mastery / (mastery + 1400) + reactionIncrease);
        }
        int totalDmg = (int) (skillDmg * atk * (1 + increase) * (1 + critRate * critDmg) * reactionMagnification * 0.5 * 0.9);
        scene.setExpectedDmg(totalDmg);
        double xrate = critRate > 0.7 ? 1:critRate;
        scene.setMaxDmg((int) (skillDmg * atk * (1 + increase) * (1 + xrate*critDmg) * reactionMagnification * 0.5 * 0.9));
    }

    public static double[] addArtifacts(double[] p1, double[] p2) {
        if (p1 == null) {
            return p2;
        }
        double[] sum = new double[p1.length];
        for (int i = 0; i < p1.length; i++) {
            sum[i] = p1[i] + p2[i];
        }

        return sum;
    }

    public static CalcData incrementCalc(double[] artifact) {
        Set<List<double[]>> all = getLists(artifact);
        if (all.size() == 0) {
            return null;
        }

        double maxExpectDmg = historyMaxExpect.get();
        double maxDmg = historyMax.get();
        List<double[]> maxExpectScene = historyMaxExpectScene.get();
        List<double[]> maxDmgScene = historyMaxScene.get();
        double maxScore = 0;
        double x = 0;
        for (List<double[]> suit : all) {
            CharacterScene scene = Hutao.getCharterFinalProperties(suit);
            CalcUtils.calcTotalDmg(scene);
            double expectedDmg = scene.getExpectedDmg();
            double maxBigNum = scene.getMaxDmg();

            List<double[]> sceneArts = scene.getSceneArts();
            if (maxExpectDmg < expectedDmg) {
                maxExpectDmg = expectedDmg;
                maxExpectScene = sceneArts;
            }

            if(sceneArts.get(0)[22] == maxScore ){
                x = Math.max(maxBigNum,x);
            }

            if (maxDmg < maxBigNum) {
                maxDmg = maxBigNum;
                maxDmgScene = sceneArts;
            }
        }
        return getCalcData(maxExpectDmg, maxDmg, maxExpectScene, maxDmgScene);
    }

    private static Set<List<double[]>> getLists(double[] artifact) {
        System.out.printf("%s,%s,%s,%s,%s, \n", ArtifactUtils.FLOWER_LIST.size(),
                ArtifactUtils.PLUME_LIST.size(),
                ArtifactUtils.EON_LIST.size(),
                ArtifactUtils.GOBLET_LIST.size(),
                ArtifactUtils.CIRCLET_LIST.size());
        int slot = (int) artifact[0];
        ImmutableSet<double[]> f_set = slot == 0 ? ImmutableSet.of(artifact) : ImmutableSet.copyOf(ArtifactUtils.FLOWER_LIST);
        ImmutableSet<double[]> p_set = slot == 1 ? ImmutableSet.of(artifact) : ImmutableSet.copyOf(ArtifactUtils.PLUME_LIST);
        ImmutableSet<double[]> e_set = slot == 2 ? ImmutableSet.of(artifact) : ImmutableSet.copyOf(ArtifactUtils.EON_LIST);
        ImmutableSet<double[]> g_set = slot == 3 ? ImmutableSet.of(artifact) : ImmutableSet.copyOf(ArtifactUtils.GOBLET_LIST);
        ImmutableSet<double[]> c_set = slot == 4 ? ImmutableSet.of(artifact) : ImmutableSet.copyOf(ArtifactUtils.CIRCLET_LIST);

        return Sets.cartesianProduct(f_set, p_set, e_set, g_set, c_set);
    }

    public static AtomicInteger historyMax = new AtomicInteger(0);
    public static AtomicInteger historyMaxExpect = new AtomicInteger(0);
    public static AtomicReference<List<double[]>> historyMaxScene = new AtomicReference<>(null);
    public static AtomicReference<List<double[]>> historyMaxExpectScene = new AtomicReference<>(null);

    private static CalcData getCalcData(double expectDmg, double maxDmg, List<double[]> maxExceptScene, List<double[]> maxScene) {
        historyMaxExpectScene.set(maxExceptScene);
        historyMaxScene.set(maxScene);

        CalcData calcData = new CalcData();
        calcData.setName("hutao");
        calcData.setExpectDmg(expectDmg);
        calcData.setMaxDmg(maxDmg);

        historyMax = new AtomicInteger((int) maxDmg);
        historyMaxExpect = new AtomicInteger((int) expectDmg);

        calcData.setMaxDmgProperties(maxScene);
        calcData.setExpectDmgProperties(maxExceptScene);

        return calcData;
    }
}
